package svcnode;

import java.io.File;
import java.net.DatagramSocket;
import java.net.ServerSocket;
import java.net.InetSocketAddress;
import java.nio.channels.ServerSocketChannel;

import soar.basic.*;

import svcnode.share.*;
import svcnode.worker.Worker;
import svcnode.worker.netlog.Netlog;
import svcnode.worker.session.Session;
import svcnode.worker.session.SessionCleaner;
import svcnode.monitor.Monitor;

public class Server
{
    private String __CLASS__=Server.class.getName();

    public boolean start(boolean debug)
    {//{{{
        final String __METHOD_="start";

        Cnfg cnfg=Cnfg.getInstance();
        if(!cnfg.load())
        {
            System.out.println(String.format("%s.%s: load cnfg fail",
                        __CLASS__, __METHOD_));
            return false;
        }

        Operate operate=Operate.getInstance();
        operate.init();

        Stat stat=Stat.getInstance();
        stat.init();

        if(!debug)
        {
            int res=Errlog.init("svcnode", cnfg.log.location);
            if(res != 0)
            {
                System.out.println(String.format(
                            "%s.%s: Errlog.init(%s) fail, res:%d",
                            __CLASS__, __METHOD_, cnfg.log.location, res));
                return false;
            }
        }

        try
        {
            DatagramSocket netlog_sock=
                new DatagramSocket(cnfg.access.server_port);
            new Netlog(netlog_sock).start();

            if(cnfg.session.enable)
            {
                Session session=Session.getInstance();
                if(session.init() == false)
                {
                    return false;
                }
                new SessionCleaner().start();
            }

            ServerSocketChannel server_channel=ServerSocketChannel.open();
            ServerSocket server_sock=server_channel.socket();
            server_sock.bind(new InetSocketAddress(
                        cnfg.access.server_port));
            server_channel.configureBlocking(false);
            for(int worker_idx=0; worker_idx<cnfg.workers; ++worker_idx)
            {
                new Worker(worker_idx, server_channel).start();
            }

            ServerSocket monitor_sock=
                new ServerSocket(cnfg.access.monitor_port);
            new Monitor(monitor_sock).start();

            server_sock.close();
            monitor_sock.close();
        }
        catch(Exception e)
        {
            System.out.println(String.format("%s.%s: init fail: %s",
                    __CLASS__, __METHOD_, e.toString()));
            return false;
        }

        return true;
    }//}}}

    public static void main(String[] args)
    {//{{{
        boolean debug=false;
        if(args.length > 0)
        {
            String opt=args[0].toUpperCase();
            if(opt.equals("DEBUG"))
                debug=true;
        }
        new Server().start(debug);
    }//}}}
}
